[% setvar title Objects : Hierarchical calls to initializers and destructors %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Objects : Hierarchical calls to initializers and destructors</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Damian Conway &lt;<a href='mailto:damian@conway.org'>damian@conway.org</a>&gt;
  Date: 1 Sep 2000
  Last Modified: 18 Sep 2000
  Mailing List: <a href='mailto:perl6-language-objects@perl.org'>perl6-language-objects@perl.org</a>
  Number: 189
  Version: 3
  Status: Frozen</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This RFC proposes a new special method called <code>BUILD</code> that is
invoked automagically whenever an object is created. Furthermore,
it proposes that both <code>BUILD</code> and <code>DESTROY</code> methods should
be invoked hierarchically in all base classes.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>One of the major limitations of object-oriented Perl is that, unlike
most other OO languages, it does not automatically invoke the
initializers and destructors of base classes, when initializing
or destructing an object of a derived class.</p>
<p>This leads to tediously complex code in constructors and destructors
in order to manually achieve the same effect. More often, it leads to bugs.</p>
<p>It is proposed that Perl 6 introduce an automatic object initialization
mechanism, analogous to the automatic object clean-up mechanism
provided by <code>DESTROY</code> methods.</p>
<p>It is further proposed that both the initialization and destruction
mechanisms automatically call their corresponding base class versions
to ensure that complete initialization and destruction of derived
objects occurs correctly.</p>
<a name='The BUILD method'></a><h2>The <code>BUILD</code> method</h2>
<p>It is proposed that, if a class has a method named <code>BUILD</code>, that method
will be invoked automatically during any call to <code>bless</code>. It
is further proposed that <code>bless</code> be extended to take an optional argument
list after its second argument, and that this list would be passed to
any <code>BUILD</code> method invoked by the <code>bless</code>.</p>
<p>The typical constructor would then be reduced to:</p>
<pre>        package MyClass;
        
        sub new { bless {}, @_ }
        </pre>
<p>with initialization handled in a separate <code>BUILD</code> routine:</p>
<pre>        sub BUILD {
                my ($self, @ctor_data) = @_;
                # initialization of object referred to by $self occurs here
        }
        
        </pre>
<a name='Hierarchical BUILD calls'></a><h2>Hierarchical <code>BUILD</code> calls</h2>
<p>It is proposed that when an object is blessed, <i>all</i> of the <code>BUILD</code> methods
in any of its base classes are also called, and passed the argument list
appended to the invocation of <code>bless</code>. <code>BUILD</code> methods would be called
in depth-first, left-most order (i.e. ancestral <code>BUILD</code> methods would be
called before derived ones). Any given <code>BUILD</code> method would only be called
once for the same object, no matter how many separate paths its class might be
inherited through.</p>
<p>For example, given the following class hierarchy:</p>
<pre>        package Base1;

        sub new { bless {}, @_ }
        sub BUILD { print &quot;Base1::BUILD : @_\n&quot; }


        package Base2; 

        sub BUILD { print &quot;Base2::BUILD : @_\n&quot; }


        package Base3; 

        sub BUILD { print &quot;Base3::BUILD : @_\n&quot; }


        package Derived1; 
        use base qw(Base1 Base2);

        sub BUILD { print &quot;Derived1::BUILD : @_\n&quot; }


        package Derived2; 
        use base qw(Base2 Base3);

        sub BUILD { print &quot;Derived2::BUILD : @_\n&quot; }


        package Rederived1; 
        use base qw(Derived1 Derived2);

        sub BUILD { print &quot;Rederived1::BUILD : @_\n&quot; }</pre>
<p>then the call to:</p>
<pre>        $obj = Rederived-&gt;new(1..3)</pre>
<p>would print:</p>
<pre>        Base1::BUILD : 1 2 3
        Base2::BUILD : 1 2 3
        Derived1::BUILD : 1 2 3
        Base3::BUILD : 1 2 3
        Derived2::BUILD : 1 2 3
        Rederived1::BUILD : 1 2 3</pre>
<p>Note in particular that <code>Base2::BUILD</code> is only called once (as early as
possible), even though class Rederived inherits it through two distinct paths.</p>
<a name='Hierarchical DESTROY calls'></a><h2>Hierarchical <code>DESTROY</code> calls</h2>
<p>It is further proposed that when an object's destructor is invoked, all
inherited destructors would also be invoked, in depth-<i>last</i>, right-most
order. Again, each <code>DESTROY</code> for an object would be called exactly once,
regardless of how many different paths it is inherited through.</p>
<p>For example, given the following class hierarchy (with the same topology
as the example for <code>BUILD</code> above):</p>
<pre>        package Base1;

        sub new { bless {}, @_ }
        sub DESTROY { print &quot;Base1::DESTROY\n&quot; }


        package Base2; 

        sub DESTROY { print &quot;Base2::DESTROY\n&quot; }


        package Base3; 

        sub DESTROY { print &quot;Base3::DESTROY\n&quot; }


        package Derived1; 
        use base qw(Base1 Base2);

        sub DESTROY { print &quot;Derived1::DESTROY\n&quot; }


        package Derived2; 
        use base qw(Base2 Base3);

        sub DESTROY { print &quot;Derived2::DESTROY\n&quot; }


        package Rederived1; 
        use base qw(Derived1 Derived2);

        sub DESTROY { print &quot;Rederived1::DESTROY\n&quot; }</pre>
<p>then the destruction of an object:</p>
<pre>        $obj = &quot;something else&quot;;</pre>
<p>would print:</p>
<pre>        Rederived1::DESTROY
        Derived2::DESTROY
        Base3::DESTROY
        Derived1::DESTROY
        Base2::DESTROY
        Base1::DESTROY</pre>
<p>Note that <code>Base2::DESTROY</code> is only called once (as late as possible),
even though class Rederived inherits it through two distinct paths.</p>
<p>Note too that the <code>DESTROY</code> invocation sequence is the exact reverse
of the sequence for <code>BUILD</code>.</p>
<a name='The REBUILD method'></a><h3>The <code>REBUILD</code> method</h3>
<p>When a blessed object is reblessed into a different class, the <code>REBUILD</code>
methods of the <i>new</i> class (and its ancestors) would be called, rather than
it's <code>BUILD</code> methods. The <code>REBUILD</code>s would be called in the
same &quot;ancestor-first&quot; sequence as for <code>BUILD</code>.</p>
<p>As well as any arguments passed to the <code>bless</code>, <code>REBUILD</code> would also be
passed -- as its second argument -- the name of the previous package,
so it could choose to invoke any cleanup methods from that package if
it so desired.  For example:</p>
<pre>        # Full &quot;destroy/create transfer&quot; on reblessing...

        sub REBUILD {
                my ($self, $oldclass, @blessargs) = @_;
                $cleanup = &quot;${oldclass}::DESTROY&quot;;
                $self-&gt;$cleanup();
                $self-&gt;BUILD(@blessargs);
        }</pre>
<p>versus:</p>
<pre>        # Simple &quot;clear private data&quot; on reblessing

        sub REBUILD {
                my ($self, $oldclass, @blessargs) = @_;
                @{$self}{grep /^_/ keys @$self} = ();
        }</pre>
<a name='Proposed standard UNIVERSAL::new'></a><h2>Proposed standard <code>UNIVERSAL::new</code></h2>
<p>Given that most Perl classes are hash-based and that the <code>BUILD</code> method
cleanly separate construction and initialization, it might be desirable to
have the UNIVERSAL class always supply a default constructor:</p>
<pre>        package UNIVERSAL;
        
        sub new { bless {}, @_ }
        </pre>
<p>If this were provided, many classes could simply define an appropriate
<code>BUILD</code> method and simply inherit their constructor.</p>
<a name='Alternative naming schemes'></a><h2>Alternative naming schemes</h2>
<p>During discussions on this RFC, some people indicated a preference for
<code>BLESS</code>/<code>REBLESS</code> or <code>NEW</code>/<code>RENEW</code>, rather than <code>BUILD</code>/<code>REBUILD</code>.</p>
<a name='MIGRATION ISSUES'></a><h1>MIGRATION ISSUES</h1>
<p>Changes to the behaviour of DESTROY might have serious impact on code
that overrides destructors in derived classes, especially if the overridden
destructor delegates explicitly to its base class counterpart.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Not difficult.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p><i>perltoot</i></p>
<p>Conway, <i>Object Oriented Perl</i>, pp. 171-178.</p>
</div>
